package ThematicModelProto;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.aetrion.flickr.Flickr;
import com.aetrion.flickr.photos.Photo;
import com.aetrion.flickr.photos.PhotoList;
import com.aetrion.flickr.photos.PhotosInterface;
import com.aetrion.flickr.photos.SearchParameters;
import com.aetrion.flickr.tags.Tag;

public class FlickrFabulaBuilder {
	
	static Integer noise = 0;
	static int apiAttempts = 4;
	static int searchAttempts = 10; // the flickr API can be inconsistent finding new results. Stop searching if the corpus hasnt grown for this many consecutive searches.
	
	public static void main(String[] args){
		try {
			String fileName = args[0].replaceAll(" ","").toLowerCase()+args[1]+".fab";;
		
			for(int i=2; i<args.length; i++){
				if(args[i].equals("-noise")){
					i++;
					noise = new Integer(args[i]);
				}
				if(args[i].equals("-o")){
					i++;
					fileName = args[i];
				}
			}
				
	
			Integer fabulaSize = new Integer(args[1]);
			Document document = generateFabula(args[0], fabulaSize.intValue());
	
			
			if(fileName.equals("-")){
				System.out.println(Helpers.xmlToString(document));
				return;
			}
			
			File f = new File(fileName);
			
			try {
		        BufferedWriter out = new BufferedWriter(new FileWriter(f));
		        out.write(Helpers.xmlToString(document));
		        out.close();
		    } catch (IOException e) {
		    	e.printStackTrace();
		    }
		    if(noise > 1){
		    	System.err.println("... natoms written.");
		    }
		}catch(Exception e){
			System.err.println(FlickrFabulaBuilder.getHelp());
		}
	    
	}
	
	public static Document generateFabula(String keyword, int fabulaSize){
		HashMap<String, Natom> natoms = new HashMap<String, Natom>();
		
		if(noise > 1){
			System.err.println("Generating Fabula: "+keyword+"-"+fabulaSize);
		}

		natoms = loadNatomsKeyword(keyword, fabulaSize);
		
		Document doc = Helpers.db.newDocument();
		
		Element fabula = doc.createElement("fabula");
		fabula.setAttribute("name", keyword);
		fabula.setAttribute("size", fabulaSize+"");
		doc.appendChild(fabula);
		
		if(noise > 3){
			System.err.println("Writing natoms ...");
		}
		
		Iterator<String> it = natoms.keySet().iterator();
		
		while(it.hasNext()){
			fabula.appendChild(natoms.get(it.next()).toXML(doc));
		}
			
	    return doc;
	}

	public static HashMap<String, Natom> loadNatomsKeyword(String m, int fabulaSize){
		HashMap<String, Natom> natoms = new HashMap<String, Natom>();
			
		Flickr f = new Flickr("2e21c9b6c0c82892eff7e4e7ee0bd35d");
		
		PhotosInterface pi = new PhotosInterface("2e21c9b6c0c82892eff7e4e7ee0bd35d", f.getTransport());
		SearchParameters searchParams = new SearchParameters();
		
		searchParams.setText(m);
		searchParams.setSort(SearchParameters.RELEVANCE);
		searchParams.setExtrasTags(true);
		
		if(noise > 2){
			System.err.println("Aquiring natoms using Flickr search with "+m+" as keyword with size "+fabulaSize);
		}
		
		int searchFails = 0;
		int lastNatomSize = 0;
		for(int page = 0; natoms.size() < fabulaSize; page++){
			
			if(noise > 3){
				System.err.println("Getting natoms for page "+page + ", natom list "+natoms.size());
			}
			
			// some times the flickr falls over a bit so we retry this.attempts number of times
			PhotoList photoList=null;
			for(int i=0; i < apiAttempts; i++){
				try{
					photoList = pi.search(searchParams, fabulaSize, page);
					break;
				}catch(Exception e){
					e.printStackTrace();
				}
				if(i == apiAttempts){
					System.err.println("Flickr api has broken after "+apiAttempts+" attempts so we're giving up...");
					System.exit(1);
				}
			}
			
			for(int i = 0; i<photoList.size(); i++){
				Photo p = (Photo)photoList.get(i);

				HashSet<String> tagslist = new HashSet<String>();

				for(Object tag: p.getTags()){
					String utf8tag;
					try {
						utf8tag = new String(((Tag)tag).getValue().toLowerCase().getBytes("UTF-8"),"UTF-8");
						tagslist.add(utf8tag);
					} catch (UnsupportedEncodingException e) {
						System.err.println("cant convert tags to utf-8, this should never happen");
					}
					
				}
				Natom natom = new Natom(p.getId(), p.getSmallUrl(), tagslist, p.getOwner().getId());
				natoms.put(p.getId(), natom);	
			}
			
			if(lastNatomSize == natoms.size()){
				searchFails++;
			}else{
				searchFails = 0;
			}
			
			lastNatomSize = natoms.size();
			if(searchFails == searchAttempts){
				if(noise > 0){
					System.err.println("After "+searchAttempts+" search attempts the Flickr API returned no more images. Finishing at "+natoms.size());
				}
				break;
			}
		}

		if(noise > 2){
			System.err.println("... natom classes written.");
		}
		
		return natoms;
	}
	
	public static String getHelp(){
		String help = "Flickr Fabula Builder Usage:\n";
		help += "\t flickrfab <keyword> <fabula_size> [-o output_file] [-noise int]";
		return help;
	}
}

